
#[allow(unused)]
#[cfg(test)]
mod tests {
    use moss_core::from_meta::FromMeta;
    use moss_core::error::Error;
    use quote::ToTokens;
    use syn::parse::ParseStream;
    use syn::parse_quote;
    use syn::Attribute;
    use syn::Expr;
    use syn::MetaList;
    use syn::MetaNameValue;
    use syn::Result;
    use syn::Token;
    use syn::{parse::Parse, Lit, Meta};

    pub struct Word;

    pub struct NamedStruct {
        name: Str,
        age: Str,
    }

    pub struct Str(pub String);

    impl TryFrom<&Expr> for Str {
        type Error = syn::Error;

        fn try_from(value: &Expr) -> std::result::Result<Self, Self::Error> {
            todo!()
        }
    }

    impl FromMeta for NamedStruct {
        #[allow(unused_variables)]
        fn from_path(path: &syn::Path) -> syn::Result<Self> {
            if path.is_ident("validate") {
                return Ok(Self {
                    name: Str(String::default()),
                    age: Str(String::default()),
                });
            }
            let shape = path.to_token_stream().to_string();
            Err(Error::unsupported_shape(&shape).into())
        }

        fn from_list(list: &syn::MetaList) -> syn::Result<Self> {
            if list.path.is_ident("") {
                let result = list.parse_args_with(|steream: syn::parse::ParseStream| -> syn::Result<Self> {
                    let list: syn::MetaList = steream.parse()?;
                    list.parse_args_with(|steream: syn::parse::ParseStream| -> syn::Result<Self> {
                        let mut _unname1: Option<Lit> = steream.parse()?;
                        if steream.is_empty() {
                            return Err(Error::too_few_items(3).into())
                        }
                        let _: syn::Token![,] = steream.parse()?;
                        if !steream.is_empty() {
                            return Err(Error::too_many_items(3).into())
                        }
                        // Ok(Self (
                        //     name: _1,
                        // ))
                        todo!()
                    })?;
                    let mut value_: Option<Str> = None;
                    let mut age_: Option<Str> = None;
                    let mut matched = false;
                    loop {
                        if matched {
                            if steream.is_empty() {
                                break;
                            }
                            let _: syn::Token![,] = steream.parse()?;
                            if steream.is_empty() {
                                break;
                            }
                        }
                        matched = false;
                        let meta: syn::Meta = steream.parse()?;
                        match &meta {
                            Meta::Path(syn_path) => {
                                if syn_path.is_ident("") {
                                    let t = Some(Word);
                                    matched = true;
                                    continue;
                                }
                            }
                            Meta::List(syn_list) => {
                                if syn_list.path.is_ident("") {
                                    let t = syn_list.parse_args_with(
                                        |steream: syn::parse::ParseStream| -> syn::Result<Option<syn::Path>> {
                                            let path: syn::Path = steream.parse::<syn::Path>()?;
                                            Ok(Some(path))
                                        },
                                    )?;
                                    matched = true;
                                    continue;
                                }
                            }
                            Meta::NameValue(syn_nv) => {
                                let syn_nv: syn::MetaNameValue = steream.parse()?;
                                if syn_nv.path.is_ident("len") {
                                    value_ = Some(Str::try_from(&syn_nv.value)?);
                                    matched = true;
                                    continue;
                                }
                                if syn_nv.path.is_ident("age") {
                                    age_ = Some(Str::try_from(&syn_nv.value)?);
                                    matched = true;
                                    continue;
                                }
                            }   
                        }
                    }
                    let result = Self {
                        name: value_.ok_or(Error::unknown_field("name"))?,
                        age: age_.unwrap(),
                    };
                    Ok(result)
                });
                if result.is_ok() {
                    return result
                }
                let result = list.parse_args_with(|stream: ParseStream| -> syn::Result<Self> {
                    todo!()
                });
            }
            if list.path.is_ident("") {
                todo!()
            }
            let shape = list.to_token_stream().to_string();
            Err(Error::unsupported_shape(&shape).into())
        }

        #[allow(unused_variables)]
        fn from_name_value(name_value: &syn::MetaNameValue) -> syn::Result<Self> {
            let path = &name_value.path;
            let value = &name_value.value;
            let value = value.try_into().unwrap();
            if path.is_ident("ident") {
                return Ok(Self {
                    name: value,
                    age: Str(String::default()),
                });
            }
            let shape = name_value.to_token_stream().to_string();
            Err(Error::unsupported_shape(&shape).into())
        }
    }

    pub struct MetaData<T: FromMeta>(pub T);

    impl<T: FromMeta> Parse for MetaData<T> {
        fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
            let meta: Meta = input.parse()?;
            let data = T::from_meta(&meta)?;
            Ok(Self(data))
        }
    }

    pub struct NamedLenConstrait {
        pub min: Option<Lit>,
        pub max: Option<Lit>,
    }

    pub struct UnnamedLenConstrait(Lit, Lit);

    pub enum Validate {
        // rename
        Len(NamedLenConstrait),
        Len1(NamedLenConstrait),
    }

    impl FromMeta for NamedLenConstrait {
        fn from_list(list: &syn::MetaList) -> Result<Self> {
            let result = list.parse_args_with(|stream: ParseStream| -> syn::Result<Self> {
                if !list.path.is_ident("named") {
                    return Err(Error::unsupported_shape(&list.tokens.to_string()).into());
                }
                let mut min = None;
                let mut max = None;
                let expr: MetaNameValue = stream.parse()?;
                if expr.path.is_ident("min") {
                    if let Expr::Lit(lit) = expr.value {
                        min = Some(lit.lit)
                    }
                } else if expr.path.is_ident("max") {
                    if let Expr::Lit(lit) = expr.value {
                        max = Some(lit.lit)
                    }
                }
                if !stream.is_empty() {
                    let comma: Token![,] = stream.parse()?;
                }
                let expr: MetaNameValue = stream.parse()?;
                if !stream.is_empty() {
                    let comma: Token![,] = stream.parse()?;
                }
                if expr.path.is_ident("min") {
                    if let Expr::Lit(lit) = expr.value {
                        min = Some(lit.lit)
                    }
                } else if expr.path.is_ident("max") {
                    if let Expr::Lit(lit) = expr.value {
                        max = Some(lit.lit)
                    }
                }
                Ok(NamedLenConstrait { min, max })
            })?;
            Ok(result)
        }
    }

    impl Parse for NamedLenConstrait {
        fn parse(input: ParseStream) -> syn::Result<Self> {
            let meta: Meta = input.parse()?;
            let data = Self::from_meta(&meta)?;
            Ok(data)
        }
    }

    impl FromMeta for Validate {
        fn from_list(list: &syn::MetaList) -> Result<Self> {
            let result = list.parse_args_with(|stream: ParseStream| -> syn::Result<Self> {
                if !list.path.is_ident("validate") {
                    return Err(Error::unsupported_shape(&list.tokens.to_string()).into());
                }
                let meta_list: syn::MetaNameValue = stream.parse()?;
                let meta_list: syn::Path = stream.parse()?;
                let meta_list: MetaList = stream.parse()?;
                if meta_list.path.is_ident("len") {
                    let value =
                        meta_list.parse_args_with(|stream: ParseStream| -> syn::Result<Self> {
                            let named = <NamedLenConstrait as Parse>::parse(stream)?;
                            if !stream.is_empty() {
                                let comma: Token![,] = stream.parse()?;
                            }
                            // let __variant0 =
                            let value = Self::Len(named);
                            Ok(value)
                        });
                    if let Ok(value) = value {
                        return Ok(value);
                    }
                }
                Err(Error::unsupported_shape(&list.tokens.to_string()).into())
            })?;
            Ok(result)
            // let mut a = 12;
            // let result = list.parse_nested_meta(|nest_meta| {
            //     if nest_meta.path.is_ident("validate") {}
            //     a = 23;
            //     return Err(Error::unsupported_shape(&list.tokens.to_string()).into());
            // });
            // return Err(Error::unsupported_shape(&list.tokens.to_string()).into());
        }
    }

    impl Parse for Validate {
        fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
            let meta: Meta = input.parse()?;
            let data = Self::from_meta(&meta)?;
            Ok(data)
        }
    }

    #[test]
    fn aa() {
        let input: Attribute = parse_quote! {
            #[validate(len(named(min = 23, max = 32)))]
        };
        let result = Validate::from_meta(&input.meta);
        match result {
            Ok(_d) => {
                println!("ok");
            }
            Err(e) => {
                println!("{e:?}");
            }
        }
    }
}

#[allow(unused)]
#[cfg(test)]
mod tests_from_attrs {
    use syn::{LitInt};

    #[derive(moss::from_meta::FromMeta)]
    pub struct Len(pub LitInt, pub LitInt);

    #[derive(moss::from_meta::FromMeta)]
    pub struct Validate(pub Len, pub Option<LitInt>);

    pub struct Container {
        pub constraits: Option<Validate>,
    }

    impl TryFrom<&Vec<syn::Attribute>> for Container {
        type Error = syn::Error;
    
        fn try_from(value: &Vec<syn::Attribute>) -> Result<Self, Self::Error> {
            let mut constraints = <Option<Validate> as moss::from_attrs::FromAttrs>::init();
            let mut matched = false;
            for attr in value {
                matched = <Option<Validate> as moss::from_attrs::FromAttrs>::visit_attr(&mut constraints, attr, "constraits")?;
                if matched {
                    break;
                }
            }
            if !matched {
                return Err(moss::error::Error::custom("no attribute matched!").into());
            }
            let result = Self {
                constraits: <Option<Validate> as moss::from_attrs::FromAttrs>::finish(constraints, "constraits")?,
            };
            Ok(result)
        }
    }
}